home *** CD-ROM | disk | FTP | other *** search
- unit DragScrollU;
-
- interface
-
- uses
- Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
- StdCtrls, ExtCtrls, ComCtrls;
-
- type
- TScrollDir = (sdUp, sdLeft, sdDown, sdRight);
- TScrollDirs = set of TScrollDir;
-
- type
- TForm1 = class(TForm)
- Memo1: TMemo;
- Label1: TLabel;
- TreeView1: TTreeView;
- Timer1: TTimer;
- procedure FormCreate(Sender: TObject);
- procedure SharedDragOver(Sender, Source: TObject; X, Y: Integer;
- State: TDragState; var Accept: Boolean);
- procedure Timer1Timer(Sender: TObject);
- private
- ScrollDirs: TScrollDirs;
- Ctrl: TWinControl;
- end;
-
- var
- Form1: TForm1;
-
- implementation
-
- {$R *.DFM}
-
- uses
- {$ifdef Ver90} { Delphi 2.0x }
- OLE2;
- {$else}
- ActiveX;
- {$endif}
-
- procedure TForm1.FormCreate(Sender: TObject);
- begin
- TreeView1.FullExpand;
- end;
-
- procedure TForm1.SharedDragOver(Sender, Source: TObject; X, Y: Integer;
- State: TDragState; var Accept: Boolean);
- var
- Style, ExStyle, //Control's windows style and extended window style
- HorzSclHt, VertSclWd, //Scroll bar sizes
- Left, Right, Top, Bottom: Integer;
- begin
- Ctrl := Sender as TWinControl;
- case State of
- dsDragEnter,
- dsDragLeave: Timer1.Enabled := False;
- dsDragMove:
- begin
- //Get window styles to see if there are scroll bars/borders
- Style := GetWindowLong(Ctrl.Handle, GWL_STYLE);
- ExStyle := GetWindowLong(Ctrl.Handle, GWL_EXSTYLE);
- //Record scroll bar size, taking into account they might not be there
- HorzSclHt := 0;
- VertSclWd := 0;
- if Style and WS_HSCROLL <> 0 then
- HorzSclHt := GetSystemMetrics(SM_CYHSCROLL);
- if Style and WS_VSCROLL <> 0 then
- VertSclWd := GetSystemMetrics(SM_CXVSCROLL);
- //Record bounding dimensions of control's area,
- //taking into account borders and scroll bars
- Left := 0;
- Top := 0;
- Right := Ctrl.Width - 1 - VertSclWd;
- Bottom := Ctrl.Height - 1 - HorzSclHt;
- if (Style and WS_BORDER <> 0) or (ExStyle and WS_EX_CLIENTEDGE <> 0) then
- begin
- Left := GetSystemMetrics(SM_CXEDGE);
- Top := GetSystemMetrics(SM_CYEDGE);
- Dec(Right, Left);
- Dec(Bottom, Top);
- end;
- //Check if over a scroll bar, in which case reject drop
- if ((X >= Right) and (X <= Right + VertSclWd)) or
- ((Y >= Bottom) and (Y <= Bottom + HorzSclHt)) then
- begin
- Accept := False;
- Exit;
- end;
- //Initialise to no scrolling direction
- ScrollDirs := [];
- //See if in scroll region
- if (X >= Left) and (X < Left + DD_DEFSCROLLINSET) then
- ScrollDirs := ScrollDirs + [sdLeft];
- if (X >= Right - DD_DEFSCROLLINSET) and (X < Right) then
- ScrollDirs := ScrollDirs + [sdRight];
- if (Y >= Top) and (Y < Top + DD_DEFSCROLLINSET) then
- ScrollDirs := ScrollDirs + [sdUp];
- if (Y >= Bottom - DD_DEFSCROLLINSET) and (Y < Bottom) then
- ScrollDirs := ScrollDirs + [sdDown];
- //If so, reset timer tick and record which region
- if ScrollDirs <> [] then
- begin
- Timer1.Interval := DD_DEFSCROLLDELAY;
- Timer1.Enabled := True;
- end
- end;
- end
- end;
-
- procedure TForm1.Timer1Timer(Sender: TObject);
- begin
- //Depending which region, scroll as appropriate
- if sdLeft in ScrollDirs then
- Ctrl.Perform (WM_HSCROLL, SB_LINELEFT, 0);
- if sdRight in ScrollDirs then
- Ctrl.Perform (WM_HSCROLL, SB_LINERIGHT, 0);
- if sdUp in ScrollDirs then
- Ctrl.Perform (WM_VSCROLL, SB_LINEUP, 0);
- if sdDown in ScrollDirs then
- Ctrl.Perform (WM_VSCROLL, SB_LINEDOWN, 0);
- Timer1.Interval := DD_DEFSCROLLINTERVAL
- end;
-
- end.
-